#include "stm32f10x.h"                  // Device header
#include <stdio.h> //要求Use MicroLib
#include <stdarg.h>
#include "Serial.h"
#include "OLED.h"
#define Serial_Buffer_Length 1500

u8 Serial_RxFlag = 0; //当数据与上次getString比较发生了变化时置1
u8 Serial_OvFlag = 0; //当数据充满缓冲区时置1
u8 Serial_Now_Choosed_Data = 0; //0 A 1 B
u8 Serial_RxDataA[Serial_Buffer_Length];
u8 Serial_RxDataB[Serial_Buffer_Length];
u16 Serial_DataPointer = 0;
//struct Serial_DataPackage Serial_RxPackageA = {Serial_RxDataA,0};

void Serial_Init(void)
{
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_USART1,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_9;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出，复用指的是输出由片内外设(TX1)控制，而不是由CPU控制
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;//可选奇偶校验
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位长度
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8bit
	USART_Init(USART1,&USART_InitStructure);
	
	USART_ITConfig(USART1,USART_IT_RXNE, ENABLE); //配置接收中断
	NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);
	NVIC_InitTypeDef NVIC_InitStructure;
	NVIC_InitStructure.NVIC_IRQChannel = USART1_IRQn;
	NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
	NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 1;
	NVIC_InitStructure.NVIC_IRQChannelSubPriority = 1;
	NVIC_Init(&NVIC_InitStructure);
	
	USART_Cmd(USART1,ENABLE);
}

void Serial_Init2(void)
{
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_USART2,ENABLE);
	RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA,ENABLE);
	
	GPIO_InitTypeDef GPIO_InitStructure;
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;//复用推挽输出，复用指的是输出由片内外设(TX1)控制，而不是由CPU控制
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3;
	GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
	GPIO_Init(GPIOA,&GPIO_InitStructure);
	
	USART_InitTypeDef USART_InitStructure;
	USART_InitStructure.USART_BaudRate = 9600;
	USART_InitStructure.USART_HardwareFlowControl = USART_HardwareFlowControl_None;//无硬件流控
	USART_InitStructure.USART_Mode = USART_Mode_Tx | USART_Mode_Rx;
	USART_InitStructure.USART_Parity = USART_Parity_No;//可选奇偶校验
	USART_InitStructure.USART_StopBits = USART_StopBits_1;//停止位长度
	USART_InitStructure.USART_WordLength = USART_WordLength_8b;//字长为8bit
	USART_Init(USART2,&USART_InitStructure);
	USART_Cmd(USART2,ENABLE);
}


void Serial_SendByte(u8 Byte)
{
	USART_SendData(USART1,Byte);
	while(USART_GetFlagStatus(USART1,USART_FLAG_TXE) == RESET);
	//下次USART_SendData时触发对DR的写操作则会自动清空TXE位
}

void Serial_SendArray(u8 *arr,u16 length)
{
	u16 i;
	for(i=0;i<length;i++){
		Serial_SendByte(arr[i]);
	}
}

void Serial_SendString(char *str)
{
	char *p = str;
	while(*p!=0) {
		Serial_SendByte(*p);
		p++;
	}
}

void Serial_SendStringln(char *str) {
	char *p = str;
	while(*p!=0) {
		Serial_SendByte(*p);
		p++;
	}
	Serial_SendByte('\r');
	Serial_SendByte('\n');
}

void Serial_SendNumber(u32 num) //逐位显示数字
{
	char rank[9] = {0};
	char *p = rank;
	do{
		*p = num % 10 | 0x30; //入栈
		num = num / 10;        
		p++;
	}while(num > 0);
	while(p != rank) {
		p--;
		Serial_SendByte(*p);
	}
}

void Serial_Printf(char *format,...)
{
	char string[100];
	va_list arg;
	va_start(arg,format);
	vsprintf(string,format,arg);
	va_end(arg);
	Serial_SendString(string);
}

u8 Serial_GetRxFlag(void)
{
	return Serial_RxFlag;
}

u8 Serial_GetOvFlag(void)
{
	return Serial_OvFlag;
}

void Serial_ClearRxFlag(void)
{
	Serial_RxFlag = 0;
}

u8* Serial_GetRxString(void) //返回当前保存数据的缓冲区的指针，已保存的长度可通过Serial_GetDataPointer得到
{
	Serial_ClearRxFlag();
	u8 *choosedData = Serial_Now_Choosed_Data ? Serial_RxDataB : Serial_RxDataA;
	choosedData[Serial_DataPointer] = 0;
	return choosedData;
}

void Serial_ClearRxString(void) //外部Serial_GetRxString处理完数据后应及时调用此
{
	Serial_Now_Choosed_Data ^= 1;
	Serial_DataPointer = 0;
	Serial_OvFlag = 0;
	Serial_ClearRxFlag();
}

u16 Serial_GetDataPointer(void)
{
	return Serial_DataPointer;
}


int fputc(int ch, FILE *f) //通过重写fpuc，可重定向printf到串口
{
	//Serial_SendByte(ch);
	USART_SendData(USART2,ch);
	while(USART_GetFlagStatus(USART2,USART_FLAG_TXE) == RESET);
	return ch;
}

void USART1_IRQHandler(void)
{
	if(USART_GetFlagStatus(USART1,USART_FLAG_RXNE) == SET) {
		u8 RxData = USART_ReceiveData(USART1); //读取时会自动清零标志位
		if(!Serial_OvFlag) {
			u8 *choosedData = Serial_Now_Choosed_Data ? Serial_RxDataB : Serial_RxDataA;
			Serial_RxFlag = 1;
			choosedData[Serial_DataPointer] = RxData;
			Serial_DataPointer++;
		}
		if(Serial_Buffer_Length <= Serial_DataPointer) { //缓冲区满后数据将会丢失
			Serial_OvFlag = 1;
		}
		USART_ClearITPendingBit(USART1,USART_IT_RXNE); //此行实际是不必要 的
	}
}
